package com.abl.service.system.impl;

import com.abl.common.annotation.check.Rule;
import com.abl.common.annotation.check.Rules;
import com.abl.common.cache.CacheKey;
import com.abl.common.cache.CacheService;
import com.abl.common.mybatis.dao.Dao;
import com.abl.common.mybatis.model.Dnt;
import com.abl.common.mybatis.strengthen.Wrapper;
import com.abl.domain.model.AblError;
import com.abl.domain.model.Param;
import com.abl.common.util.StringKit;
import com.abl.common.util.coll.ArrayKit;
import com.abl.common.util.coll.MapKit;
import com.abl.service.system.SysRoleService;
import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONArray;
import com.alibaba.fastjson2.JSONObject;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;

/**
 * 角色表实现
 */
@Slf4j
@Service
public class SysRoleServiceImpl implements SysRoleService {
    @Autowired
    private Dao dao;
    @Autowired
    CacheService cache;

    //新增
    @Transactional(rollbackFor = Exception.class)
    @Override
    public boolean add(Param<JSONObject> param) {
        String name = param.getString("name");
        String role_key = param.getString("role_key");
        JSONArray check_menu_ids = param.getJSONArray("check_menu_ids");

        //查未删除且重复数据
        Wrapper<Object> qw = new Wrapper<>();
        qw.eq("d_s", 0);
        qw.and(q -> {
            q.eq("name", name);
            q.or();
            q.eq("role_key", role_key);
        });
        Dnt dnt2 = dao.selectOne("sys_role", qw);
        if (dnt2 != null) {
            if (name.equals(dnt2.getString("name"))) {
                throw new AblError("操作失败：角色名称【{0}】已存在", name);
            }
            if (role_key.equals(dnt2.getString("role_key"))) {
                throw new AblError("操作失败：权限字符【{0}】已存在", role_key);
            }
        }

        //插入角色信息
        Dnt dnt = Dnt.createInsert();
        HashMap set = MapKit.set(param, Arrays.asList("sort", "status", "desc", "name", "role_key"));
        dnt.set(set);
        dnt.set("check_menu_ids", check_menu_ids.toString());
        dao.insert("sys_role", dnt);

        //更新角色菜单关联关系
        updateRoleMenu(dnt.getString("id"), param.getJSONArray("menuIds"));
        return true;
    }

    //删除
    @Override
    public boolean del(Param<JSONObject> param) {
        ArrayList<Object> ids = param.getList("ids");

        //检查是否存在关联
        Wrapper<Object> wrapper = new Wrapper<>();
        wrapper.in("role_id", ids);
        long count = dao.count("sys_link_user_role", wrapper);
        if (count > 0) {
            throw new AblError("操作失败：角色ID {0} 已被使用", ids);
        }

        //
        Wrapper<Object> uw = new Wrapper<>();
        uw.in("id", ids);
        uw.set("d_s", 1);
        dao.update("sys_role", uw);

        //清空关联角色缓存
        for (Object roleId : ids) {
            cache.delete(CacheKey.LINK_ROLE_API.key() + roleId);
        }

        return true;
    }

    //修改
    @Transactional(rollbackFor = Exception.class)
    @Override
    public boolean edit(Param<JSONObject> param) {
        //检查重复
        String roleId = param.getString("id");
        String name = param.getString("name");
        Wrapper<Object> qw = new Wrapper<>();
        qw.eq("d_s", 0);
        qw.ne("id", roleId);
        qw.eq("name", name);
        Dnt dnt2 = dao.selectOne("sys_role", qw);
        if (dnt2 != null) {
            if (name.equals(dnt2.getString("name"))) {
                throw new AblError("操作失败：角色名称【{0}】已存在", name);
            }
        }

        //更新角色信息
        Dnt dnt = Dnt.createUpdate();
        HashMap set = MapKit.set(param, Arrays.asList("sort", "status", "desc", "name", "role_key"));
        dnt.set(set);
        dnt.set("check_menu_ids", param.getJSONArray("check_menu_ids").toString());
        dnt.set("id", roleId);
        dao.updateById("sys_role", dnt);

        //更新关联菜单
        updateRoleMenu(roleId, param.getJSONArray("menuIds"));

        return true;
    }

    //修改
    @Transactional(rollbackFor = Exception.class)
    @Override
    public boolean editApi(Param<JSONObject> param) {
        String roleId = param.getString("roleId");

        //更新勾选ID
        Dnt dnt = Dnt.createUpdate();
        dnt.set("id", roleId);
        dnt.set("check_api_ids", param.getJSONArray("check_api_ids").toString());
        dao.updateById("sys_role", dnt);

        //更新关联资源
        updateRoleApi(roleId, param.getJSONArray("apiIds"));

        return true;
    }

    //查询详情
    @Override
    public Dnt info(Param<JSONObject> param) {
        Wrapper<Object> qW = new Wrapper<>();
        qW.eq("d_s", 0);
        qW.eq("id", param.getOrDefault("id", 0));
        return dao.selectOne("sys_role", qW);
    }

    //查询集合
    @Override
    public List<Dnt> list(Param<JSONObject> param) {
        String name = param.getString("name", "");
        String status = param.getString("status", "");
        String roleKey = param.getString("roleKey", "");

        Wrapper<Object> qw = new Wrapper<>();
        qw.eq("d_s", 0);
        qw.eq(StringKit.isNotBlank(param.getString("id")), "id", param.getString("id"));
        qw.eq(StringKit.isNotBlank(status), "status", status);
        qw.like(StringKit.isNotBlank(roleKey), "role_key", roleKey);
        qw.like(StringKit.isNotBlank(name), "name", name);
        qw.orderByAsc("sort");

        if (param.isPage()) {
            return dao.page("sys_role", qw, param.pageCurrent(), param.pageSize());
        } else {
            return dao.list("sys_role", qw);
        }
    }

    @Override
    public Dnt roleRes(Param<JSONObject> param) {
        String roleId = param.getString("roleId", "0");

        //全部资源
        Wrapper<Object> qW = new Wrapper<>();
        qW.eq("d_s", 0);
        qW.select("id,pid,sort,name,path");
        List<Dnt> apiList = dao.list("sys_api", qW);

        //已具备功能
        qW = new Wrapper<>();
        qW.select("menu_fun_id");
        qW.eq("role_id", roleId);
        List<Object> menuFunId = dao.listObj("sys_link_role_menu_fun", qW);
        qW = new Wrapper<>();
        qW.select("apis");
        qW.eq("d_s", "0");
        qW.in("id", menuFunId);
        List<Object> funApiInfo = dao.listObj("sys_menu_fun", qW);

        //从功能中读取，已具备ApiId
        HashSet<String> apiIdSet = new HashSet<>();
        for (Object o : funApiInfo) {
            JSONArray objects = JSON.parseArray(o.toString());
            for (Object funApi : objects) {
                apiIdSet.add(((JSONObject) funApi).getString("id"));
            }
        }

        //根据 API ID ,查询Api完整信息
        List<Object> roleApiIdList = new ArrayList<>(apiIdSet);
        List<Dnt> roleApiList = new ArrayList<>();
        if (ArrayKit.isNotBlank(roleApiIdList)) {
            qW = new Wrapper<>();
            qW.eq("d_s", 0);
            qW.in("id", roleApiIdList);
            roleApiList = dao.list("sys_api", qW);
        }

        Dnt dnt = Dnt.create();
        dnt.set("resList", apiList);
        dnt.set("roleRes", roleApiList);
        dnt.set("roleResId", roleApiIdList);

        return dnt;
    }

    @Override
    public Dnt roleMenu(Param<JSONObject> param) {
        String roleId = param.getString("roleId", "0");

        //全部菜单
        Wrapper<Object> qW = new Wrapper<>();
        qW.eq("d_s", 0);
        qW.select("*");
        List<Dnt> menuList = dao.list("sys_menu", qW);

        //已具备资源Id
        qW = new Wrapper<>();
        qW.select("menu_id");
        qW.eq("role_id", roleId);
        List<Object> roleMenuIds = dao.listObj("sys_link_role_menu", qW);

        //已具备资源
        List<Dnt> roleMenu = new ArrayList<>();
        if (ArrayKit.isNotBlank(roleMenuIds)) {
            qW = new Wrapper<>();
            qW.eq("d_s", 0);
            qW.in("id", roleMenuIds);
            roleMenu = dao.list("sys_menu", qW);
        }

        Dnt dnt = Dnt.create();

        dnt.set("menuList", menuList);
        dnt.set("roleMenu", roleMenu);
        dnt.set("roleMenuIds", roleMenuIds);
        return dnt;

    }

    @Transactional(rollbackFor = Exception.class)
    @Rules({@Rule(key = "roleId,", rule = "notNull"), @Rule(key = "res", rule = {"list", "notNull"}),})
    public boolean editRoleApi(Param<JSONObject> param) {
        String roleId = param.getString("roleId");
        ArrayList<Object> apiIds = param.getList("apiIds");

        //删除关联关系
        //        Wrapper<Object> qw = new Wrapper<>();
        //        qw.eq("role_id", roleId);
        //        dao.delete("sys_link_role_api", qw);

        //更新关联关系
//        Wrapper<Object> qw = new Wrapper<>();
//        qw.eq("de_s", 0);
//        qw.in("id", apiIds);
//        qw.select("path");
//        List<String> apiPath = dao.listObj("sys_api", qw, String.class);
//        ArrayList<Dnt> dnts = new ArrayList<>();
//        for (Object path : apiPath) {
//            Dnt dnt = Dnt.create();
//            dnt.set("role_id", roleId);
//            dnt.set("api_path", path);
//            dnts.add(dnt);
//        }
//        long sys_link_role_api = dao.insertBatch("sys_link_role_api", dnts);

        return true;
    }

    //模糊查询条件下拉列表
    @Override
    public List<Dnt> searchInput(Param<JSONObject> param) {
        String role_name = param.getOrDefault("role_name", "") + "";
        String menu_name = param.getOrDefault("menu_name", "") + "";
        String res_name = param.getOrDefault("res_name", "") + "";

        Wrapper<Object> qw = new Wrapper<>();
        qw.eq("d_s", 0);
        qw.last(" limit 30 ");

        //角色名
        if (StringKit.isNotBlank(role_name)) {
            qw.select("name");
            qw.like("name", role_name);
            qw.groupBy("name");
            return dao.list("sys_role", qw);
        }

        //菜单名称
        if (StringKit.isNotBlank(menu_name)) {
            qw.select("name");
            qw.like("name", menu_name);
            qw.groupBy("name");
            return dao.list("sys_menu", qw);
        }

        //资源名称
        if (StringKit.isNotBlank(res_name)) {
            qw.select("name");
            qw.like("name", res_name);
            qw.groupBy("name");
            return dao.list("sys_api", qw);
        }

        return new ArrayList<>();
    }

    //"menuIds":["100000",         "20000"]
    private void updateRoleMenu(String roleId, JSONArray menuIds) {
        Wrapper<Object> qw = new Wrapper<>();
        qw.eq("role_id", roleId);
        dao.delete("sys_link_role_menu", qw);
        ArrayList<Dnt> linkMenu = new ArrayList<>();
        if (ArrayKit.isNotBlank(menuIds)) {
            menuIds.forEach(menu_id -> {
                Dnt dnt1 = Dnt.create();
                dnt1.set("role_id", roleId);
                dnt1.set("menu_id", menu_id);
                linkMenu.add(dnt1);
            });
            dao.insertBatch("sys_link_role_menu", linkMenu);
        }
    }

    private void updateRoleApi(String roleId, JSONArray apiIds) {
        Wrapper<Object> qw = new Wrapper<>();
        qw.eq("role_id", roleId);
        dao.delete("sys_link_role_menu", qw);
        ArrayList<Dnt> linkMenu = new ArrayList<>();
        apiIds.forEach(menu_id -> {
            Dnt dnt1 = Dnt.create();
            dnt1.set("role_id", roleId);
            dnt1.set("menu_id", menu_id);
            linkMenu.add(dnt1);
        });
        dao.insertBatch("sys_link_role_menu", linkMenu);
    }


}


//    @Transactional
//    @Override
//    public long editRoleMenu(Param<JSONObject> param) {
//        String roleId = param.getString("roleId");
//        ArrayList<Object> deleteId = param.getList("deleteId");
//        ArrayList<Object> checkId = param.getList("checkId");
//
//        //遍历树结构
//        HashSet<Object> delId = new HashSet<>();
//        HashSet<Object> ckId = new HashSet<>();
//        for (Object menuId : checkId) {
//            suppId(menuId, delId, ckId);
//        }
//        delId.addAll(deleteId);
//        ckId.addAll(checkId);
//
//        //删除关联
//        Wrapper<Object> qw = new Wrapper<>();
//        qw.eq("role_id", roleId);
//        qw.in("menu_id", delId);
//        dao.delete("sys_link_role_menu", qw);
//
//        //添加关联
//        ArrayList<Dnt> menus = new ArrayList<>();
//        for (Object mId : ckId) {
//            Dnt dnt = Dnt.create();
//            dnt.set("role_id", roleId);
//            dnt.set("menu_id", mId);
//            menus.add(dnt);
//        }
//        return dao.insertBatch("sys_link_role_menu", menus);
//    }


//递归遍历树
//    private void suppId(Object menuId, HashSet<Object> delId, HashSet<Object> ckId) {
//        Wrapper<Object> qw = new Wrapper<>();
//        qw.select("id");
//        qw.eq("d_s", 0);
//        qw.eq("pid", menuId);
//        List<Object> menuIds = dao.listObj("sys_menu", qw);
//        delId.addAll(menuIds);
//        ckId.addAll(menuIds);
//        for (Object menuId_ : menuIds) {
//            suppId(menuId_, delId, ckId);
//        }
//    }


/**
 * 查询角色对应全部功能
 * <p>
 * 修改角色对应功能关联关系
 * <p>
 * 修改角色对应功能关联关系
 * <p>
 * 修改角色对应功能关联关系
 * <p>
 * 修改角色对应功能关联关系
 * <p>
 * 修改角色对应功能关联关系
 * <p>
 * 修改角色对应功能关联关系
 * <p>
 * 修改角色对应功能关联关系
 * <p>
 * 修改角色对应功能关联关系
 * <p>
 * 修改角色对应功能关联关系
 * <p>
 * 修改角色对应功能关联关系
 * <p>
 * 修改角色对应功能关联关系
 * <p>
 * 修改角色对应功能关联关系
 * <p>
 * 修改角色对应功能关联关系
 * <p>
 * 修改角色对应功能关联关系
 * <p>
 * 修改角色对应功能关联关系
 * <p>
 * 修改角色对应功能关联关系
 * <p>
 * 修改角色对应功能关联关系
 */
//    @Override
//    public Dnt roleMenuFun(Param<JSONObject> param) {
//        String roleId = param.getString("roleId", "0");
//
//        //角色功能
//        Wrapper<Object> qW = new Wrapper<>();
//        qW.eq("role_id", roleId);
//        qW.select("menu_fun_id");
//        List<Object> roleFunId = dao.listObj("sys_link_role_menu_fun", qW);
//
//        //角色菜单
//        qW.select("menu_id");
//        qW.eq("role_id", roleId);
//        List<Object> roleMenuIds = dao.listObj("sys_link_role_menu", qW);
//
//        //菜单信息
//        List<Dnt> menuList = new ArrayList<>();
//        if (roleMenuIds.size() != 0) {
//            qW = new Wrapper<>();
//            qW.select("id,name");
//            qW.eq("d_s", 0);
//            qW.eq("type", 1);
//            qW.in("id", roleMenuIds);
//            menuList = dao.list("sys_menu", qW);
//        }
//        //功能信息
//        JSONArray menAndFunList = JSON.parseArray(JSON.toJSONString(menuList));
//        for (Object menu : menAndFunList) {
//            qW = new Wrapper<>();
//            qW.select("id, name, menu_id ");
//            qW.eq("d_s", 0);
//            qW.eq("menu_id", ((JSONObject) menu).getString("id"));
//            List<Dnt> men_fun = dao.list("sys_menu_fun", qW);
//            ((JSONObject) menu).put("menu_fun", men_fun);
//        }
//
//
//        //功能信息
//        JSONArray menuFunCheckList = JSON.parseArray(JSON.toJSONString(menuList));
//        for (Object menu : menuFunCheckList) {
//            if (roleFunId.size() == 0) {
//                ((JSONObject) menu).put("menu_fun", new ArrayList<>());
//                continue;
//            }
//            qW = new Wrapper<>();
//            qW.select("id, name, menu_id ");
//            qW.eq("d_s", 0);
//            qW.eq("menu_id", ((JSONObject) menu).getString("id"));
//            qW.in("id", roleFunId);
//            List<Dnt> men_fun = dao.list("sys_menu_fun", qW);
//            ((JSONObject) menu).put("menu_fun", men_fun);
//        }
//
//        Dnt dnt = Dnt.create();
//        dnt.set("checkId", roleFunId);
//        dnt.set("menuFunList", menAndFunList);
//        dnt.set("menuFunCheckList", menuFunCheckList);
//
//        return dnt;
//    }

/**
 * 修改角色对应功能关联关系
 */
//    @Transactional(rollbackFor = Exception.class)
//    public boolean editRoleMenuFun(Param<JSONObject> param) {
//        String roleId = param.getString("roleId", "0");
//        JSONArray funIds = param.getJSONArray("funIds");
//
//        //清除-角色功能-关联关系
//        Wrapper<Object> qW = new Wrapper<>();
//        qW.eq("role_id", roleId);
//        dao.delete("sys_link_role_menu_fun", qW);
//
//        //插入-角色功能-关联关系
//        ArrayList<Dnt> objects = new ArrayList<>();
//        for (Object menu_fun_id : funIds) {
//            Dnt dnt = Dnt.create();
//            dnt.set("role_id", roleId);
//            dnt.set("menu_fun_id", menu_fun_id);
//            objects.add(dnt);
//        }
//        dao.insertBatch("sys_link_role_menu_fun", objects);
//
//        //清空关联角色缓存
//        cache.delete(CacheKey.LINK_ROLE_API.key() + roleId);
//
//        return true;
//    }


//    @Transactional(rollbackFor = Exception.class)
//    @Override
//    public boolean copyAndAdd(Param<JSONObject> param) {
//        //新增角色
//        Dnt role = Dnt.createInsert();
//        role.set("id", param.getString("id"));
//        role.set("desc", param.getString("desc"));
//        role.set("name", param.getString("name"));
//        role.set("sort", param.getString("sort"));
//        dao.insert("sys_role", role);
//
//        //插入ID
//        String id = param.getString("id");
//        //复制ID
//        String copy_id = param.getString("copy_id");
//
//        //关联菜单
//        Wrapper<Object> qw = new Wrapper<>();
//        qw.eq("role_id", copy_id);
//        qw.select("menu_id");
//        List<Object> menuIds = dao.listObj("sys_link_role_menu", qw);
//
//        ArrayList<Dnt> menus = new ArrayList<>();
//        for (Object mId : menuIds) {
//            Dnt dnt = Dnt.create();
//            dnt.set("role_id", id);
//            dnt.set("menu_id", mId);
//            menus.add(dnt);
//        }
//        dao.insertBatch("sys_link_role_menu", menus);
//
//
//        //关联菜单功能
//        qw = new Wrapper<>();
//        qw.eq("role_id", copy_id);
//        qw.select("menu_fun_id");
//        List<Object> menuFunIds = dao.listObj("sys_link_role_menu_fun", qw);
//
//        ArrayList<Dnt> menusFun = new ArrayList<>();
//        for (Object funId : menuFunIds) {
//            Dnt dnt = Dnt.create();
//            dnt.set("role_id", id);
//            dnt.set("menu_fun_id", funId);
//            menusFun.add(dnt);
//        }
//        dao.insertBatch("sys_link_role_menu_fun", menusFun);
//
//        return true;
//    }